﻿#pragma once
#include "Common.h"
//定长内存池
//template<size_t N>
//class ObjectPool
//{
//};

template<class T>
class ObjectPool
{
public:
	T* New()
	{
		T* obj = nullptr;

		//先去自由链表里面去找有没有可以重复利用的
		if (_freeList)
		{
			//头删
			//记录下一块
			void* next = *(void**)_freeList;
			obj = (T*)_freeList;
			_freeList = next;
		}
		else
		{
			//剩余内存不够分配，重新开一块
			if (_remainBytes < sizeof(T))
			{
				_remainBytes = 128 * 1024; //申请了16页内存
				//_memory = (char*)malloc(_remainBytes);
				_memory = (char*)SystemAlloc(_remainBytes >> 13); //右移13位，刚好8k
				if (_memory == nullptr)
				{
					throw std::bad_alloc();
				}
			}
			obj = (T*)_memory;
			//控制一次开内存的大小，因为我们的自由链表中，有一个指针位，所以一次性至少要有一个指针大小的内存块。比如T为char类型时，自由链表出问题了
			size_t objSize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);
			_memory += objSize;
			_remainBytes -= objSize;

		}

		//定位new，显示调用T的构造函数初始化
		new(obj)T;

		return obj;
	}
	void Delete(T* obj)
	{
		//显示调用析构函数，清理对象
		obj->~T();
		//头插入自由链表
		//*(int*)obj = nullptr; //int是4字节，只能在32位机器跑，如果64位机械那么后四个字节无法置为空。
		*(void**)obj = _freeList;//这样一定是将一个指针大小的区域给置空
		_freeList = obj;
	}
private:
	char* _memory = nullptr; //指向大块内存指针
	size_t _remainBytes = 0; //大块内存被切分过程中剩余字节数
	void* _freeList = nullptr; //还回来过程中链接的自由链表的头指针，释放队列,自由链表，小内存管理
};

struct TreeNode
{
	int _val;
	TreeNode* _left;
	TreeNode* _right;
	TreeNode()
		:_val(0)
		, _left(nullptr)
		, _right(nullptr)
	{}
};
